13-Java 的 类加载机制
DBUtil.class.getClassLoader().getResourceAsStream("config.properties") 能够找到配置文件,是因为 Java 的 类加载机制(ClassLoader) 会从 类路径(Classpath) 中查找资源文件。它的工作原理如下:
0.1.1. 1. ClassLoader 的作用
ClassLoader 是 Java 加载 .class 文件和资源文件(如 .properties、.xml 等)的核心机制。它负责:
- 加载
.class文件到 JVM 中 - 查找并读取类路径(Classpath)下的资源文件(如
config.properties)
0.1.2. 2. getResourceAsStream() 如何查找文件?
getResourceAsStream(String name) 方法会在 类路径(Classpath) 中查找指定名称的资源文件,并返回一个 InputStream。它的查找逻辑如下:
(1) 查找范围
- 类路径(Classpath) 包括:
src/main/resources/(Maven/Gradle 项目的标准资源目录)src/(传统 Java 项目的资源目录)target/classes/(Maven 编译后.class和资源文件的输出目录)- JAR 包中的文件(如果资源被打包进 JAR)
- 其他手动添加到 Classpath 的目录
(2) 查找方式
-
getResourceAsStream("config.properties")
表示从 类路径的根目录 查找config.properties文件。- 如果文件在
src/main/resources/config.properties,则可以直接找到。 - 如果文件在
src/main/resources/com/example/config.properties,则需要写完整路径:
getResourceAsStream("com/example/config.properties")
- 如果文件在
-
getResourceAsStream("/config.properties")
如果加了/,仍然表示从类路径的根目录查找(和上面一样)。
0.1.3. 3. 为什么 FileReader 不能用相对路径,而 getResourceAsStream 可以?
| 方式 | 查找依据 | 适用场景 | 问题 |
|---|---|---|---|
FileReader("config.properties") |
基于 当前工作目录(Working Directory) | 本地文件系统 | 工作目录可能因运行方式(IDE、命令行、JAR)不同而变化,导致找不到文件 |
getResourceAsStream("config.properties") |
基于 类路径(Classpath) | JAR 包、IDE、服务器环境 | 稳定,只要文件在 Classpath 中就能找到 |
FileReader 的问题
- 如果使用
new FileReader("config.properties"),Java 会在 当前工作目录(通常是项目根目录或模块目录)查找文件。 - 如果通过
java -jar运行 JAR 包,工作目录可能不同,导致找不到文件。 - 如果文件在
src/main/resources/里,编译后会被复制到target/classes/,FileReader仍然找不到。
getResourceAsStream 的优势
- 无论文件是在
src/main/resources/还是打包进 JAR,只要它在 Classpath 中,就能被找到。 - 适用于各种运行环境(IDE、命令行、Tomcat 服务器等)。
0.1.4. 4. 如何确保 config.properties 能被正确加载?
(1) 文件位置
- Maven/Gradle 项目:放在
src/main/resources/config.properties
(编译后会自动复制到target/classes/config.properties) - 传统 Java 项目:放在
src/或手动添加到 Classpath
(2) 代码加载方式
// 推荐方式:使用 ClassLoader
try (InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("config.properties")) {
if (in == null) {
throw new RuntimeException("配置文件 config.properties 未找到!");
}
Properties props = new Properties();
props.load(in);
// 读取配置...
} catch (IOException e) {
throw new RuntimeException("加载配置文件失败", e);
}
0.1.5. 5. 总结
| 关键点 | 说明 |
|---|---|
ClassLoader |
负责从 Classpath 加载 .class 和资源文件 |
getResourceAsStream() |
从 Classpath 根目录查找文件,返回 InputStream |
src/main/resources/ |
Maven/Gradle 项目的标准资源目录 |
FileReader 的问题 |
依赖工作目录,不可靠 |
getResourceAsStream 的优势 |
适用于 JAR、IDE、服务器环境,稳定可靠 |
这样,无论你的项目是在 IDE 中运行,还是打包成 JAR 文件,getResourceAsStream 都能正确找到 config.properties! 🚀